﻿using System;
using System.Collections.Generic;
using Iesi.Collections.Generic;
using ScrumBox.Library;

namespace ScrumBox.Model
{
    public class Project : EntityBase
    {
        private string _name;
        private string _description;
        private string _key;
        private DateTime? _startDate;
        private readonly ISet<Sprint> _sprints = new HashedSet<Sprint>();
        private readonly ISet<ProductBackLogItem> _productBacklogItems = new HashedSet<ProductBackLogItem>();
        
        /// <summary>
        /// Name
        /// </summary>
        public virtual string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        /// <summary>
        /// Description
        /// </summary>
        public virtual string Description
        {
            get { return _description; }
            set { _description = value; }
        }
        /// <summary>
        /// Key
        /// </summary>
        public virtual string Key
        {
            get { return _key; }
            set { _key = value; }
        }
        /// <summary>
        /// StartDate
        /// </summary>
        public virtual DateTime? StartDate
        {
            get { return _startDate; }
            set { _startDate = value; }
        }
        /// <summary>
        /// 
        /// </summary>
        public Project(){}
        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <param name="key"></param>
        /// <param name="startDate"></param>
        public Project(string name, string key, DateTime startDate)
        {
            Check.Assert(!string.IsNullOrEmpty(name));
            Check.Assert(!string.IsNullOrEmpty(key));
            Check.Assert(startDate != DateTime.MinValue);

            _name = name;
            _key = key;
            _startDate = startDate;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        public virtual void AddProductBackLogItem(ProductBackLogItem item)
        {
            Check.Assert(item != null);

            item.Project = this;
            _productBacklogItems.Add(item);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sprint"></param>
        public virtual void AddSprint(Sprint sprint)
        {
            Check.Assert(sprint != null);

            sprint.Project = this;
            _sprints.Add(sprint);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual IList<Sprint> GetSprints()
        {
            return new List<Sprint>(_sprints);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="title"></param>
        /// <returns></returns>
        public virtual Sprint GetSprint(string title)
        {
            Check.Assert(title != null);

            return new List<Sprint>(_sprints).Find(sprint => sprint.Title == title);
        }


        //TODO: Check whether we should use properties here wih a protected setter 
        //to avoid using access=Field in NHibernate. From http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual IList<ProductBackLogItem> GetProductBacklogItems()
        {
            return new List<ProductBackLogItem>(_productBacklogItems);
        }
        
        //TODO: Refactor this into IList extension methods to keep this collection management out of the project entity.
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public virtual ProductBackLogItem GetProductBacklogItem(Guid key)
        {
            return GetProductBacklogItem(b => b.Id == key);
        }

        //TODO: Refactor this into IList extension methods to keep this collection management out of the project entity.
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual ProductBackLogItem GetProductBacklogItem(string title)
        {
            return GetProductBacklogItem(b => b.Title == title);
        }

        //TODO: Refactor into a generic search extension of List<T>
        /// <summary>
        /// Generic search
        /// </summary>
        /// <param name="searchAction"></param>
        /// <returns></returns>
        public virtual ProductBackLogItem GetProductBacklogItem(Predicate<ProductBackLogItem> searchAction)
        {
            Check.Assert(searchAction != null);
            return new List<ProductBackLogItem>(_productBacklogItems).Find(searchAction);
        }
    }
}